import { Router, Request, Response } from 'express'
import { find, transaction, insert } from '../../db/dao'
import { USER, STUDENT, UserData } from '../../db/model'
import bcrypt from 'bcryptjs'

interface RequestWithBody extends Request{
  body: {
    type: string;
    data: UserData;
  };
}

/**
 * 判断用户是否已存在
 * @param type 用户类型
 * @param users 用户数据
 */
function hasUser (type: string, users: UserData | UserData[]) {
  let accounts: Array<string>
  if (Array.isArray(users)) {
    accounts = users.map(user => user.account)
  } else {
    accounts = [users.account]
  }
  return new Promise<string[]>((resolve, reject) => {
    find(STUDENT, {
      account: { $in: accounts }
    }).then(res => {
      if (res.length === 0) {
        resolve([])
      } else {
        resolve(res.map(user => (user as any).account))
      }
    }).catch(reject)
  })
}

/**
 * 添加用户
 * @param type 用户类型
 * @param values 用户数据
 */
function addUser (type: string, values: UserData | UserData[]) {
  let accountData: {} | Array<{}>
  if (Array.isArray(values)) {
    accountData = values.map(item => {
      return {
        account: item.account,
        password: item.password,
        identity: type
      }
    })
  } else {
    accountData = {
      account: values.account,
      password: values.password,
      identity: type
    }
  }
  return transaction(session => Promise.all([
    insert(USER, accountData, { session }, true),
    insert(STUDENT, values, { session }, true)
  ]))
}

/**
 * 对密码进行加密，生成新的密码
 * @param password 密码
 */
function generatePassword (password: string) {
  return new Promise<string>((resolve, reject) => {
    bcrypt.genSalt(10, function (err, salt) {
      if (err) return reject(err)
      bcrypt.hash(password, salt, (err, hash) => {
        if (err) return reject(err)
        resolve(hash)
      })
    })
  })
}

const router = Router()

router.post('/add', async (req: RequestWithBody, res: Response) => {
  const { type, data } = req.body
  if (!type || !data) {
    return res.status(400).end()
  }
  try {
    const users = await hasUser(STUDENT, data)
    if (users.length !== 0) {
      res.status(200).json({
        code: 1,
        msg: 'user existed',
        users
      })
    } else {
      if (Array.isArray(data)) {
        await Promise.all(data.map(async (item) => {
          item.password = await generatePassword(item.password.trim().length ? item.password : '123456')
        }))
      } else {
        data.password = await generatePassword(data.password.trim().length ? data.password : '123456')
      }
      await addUser(type, data)
      res.status(200).json({
        code: 0,
        msg: 'ok',
        data
      })
    }
  } catch (e) {
    console.log(e)
    res.status(500).json(e)
  }
})

export default router
